﻿/*
This project and all of its code is/are Copyright (C) 2017  Nils Hunter Alving

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;

namespace DynamicDependencyContainer.Interfaces
{
    /// <summary>
    /// A dependency injection container that dynamically creates data types from interface declarations
    /// </summary>
    public interface IDynamicUnityContainer : IResolveDependencies
    {
        /// <summary>
        /// Registers the specified type as the type to return when the specified interface is resolved
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        void RegisterType<TI, TT>() where TT : TI where TI : class;
        /// <summary>
        /// Registers the specified type as the type to return when the specified interface is resolved. The constructor
        /// with the matching parameter set (type and order) will be invoked each time resolved, and a new instance
        /// of the object will be returned
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        /// <param name="constructorParameters">The parameters to be passed to the constructor each time the object is resolved</param>
        void RegisterType<TI, TT>(object[] constructorParameters) where TT : TI where TI : class;
        /// <summary>
        /// Registers the specified type as the type to return when the specified interface is resolved. A new instance
        /// of the object will be created using the default constructor and returned each time Resovle() is called, 
        /// after it is passed to the initializer function
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        /// <param name="initializerFunction">A function that will initialize properties on the new object instance</param>
        void RegisterType<TI, TT>(Action<TI> initializerFunction) where TT : TI where TI : class;
        /// <summary>
        /// Registers the specified type as the type to return when the specified interface is resolved. The constructor
        /// with the matching parameter set (type and order) will be invoked each time Resolve() is called, and a new instance
        /// of the object will be returned after it is passed to the initializer function
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        /// <param name="constructorParameters">The parameters to be passed to the constructor each time the object is resolved</param>
        /// <param name="initializerFunction">A function that will initialize properties on the new object instance</param>
        void RegisterType<TI, TT>(object[] constructorParameters, Action<TI> initializerFunction) where TT : TI where TI : class;
        /// <summary>
        /// Registers the specified instance as the singleton to return when the specified interface is resolved
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        void RegisterInstance<TI>(object instance) where TI : class;
        /// <summary>
        /// Allows registration of a type to represent an interface, using the singleton pattern.
        /// The singleton is not created until the first time it is Resolve()'d
        /// Class must have a default constructor
        /// </summary>
        void RegisterLazyInstance<TI, TT>() where TI : class;
        /// <summary>
        /// Registers the specified instance as the singleton to return when the specified interface is resolved
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        /// <param name="constructorParams">The parameters to be passed to the constructor. The class must have a constructor
        /// with a parameter list that matches both the type and order of the specified parameters</param>
        void RegisterLazyInstance<TI, TT>(object[] constructorParams) where TT : TI where TI : class;
        /// <summary>
        /// Allows registration of a type to represent an interface, using the singleton pattern.
        /// The singleton is not created until the first time it is Resolve()'d
        /// </summary>
        /// <param name="initializerFunction">A function that will initialize properties on the new object instance</param>
        void RegisterLazyInstance<TI, TT>(Action<TI> initializerFunction) where TT : TI where TI : class;
        /// <summary>
        /// Registers the specified instance as the singleton to return when the specified interface is resolved
        /// </summary>
        /// <typeparam name="TI">An interface type</typeparam>
        /// <typeparam name="TT">A class type that implements the interface</typeparam>
        /// <param name="constructorParams">The parameters to be passed to the constructor. The class must have a constructor
        /// with a parameter list that matches both the type and order of the specified parameters</param>
        /// <param name="initializerFunction">A function that will initialize properties on the new object instance</param>
        void RegisterLazyInstance<TI, TT>(object[] constructorParams, Action<TI> initializerFunction) where TT : TI where TI : class;
        /// <summary>
        /// Dynamically creates a type from the interface declaration. Limited to interfaces that declare properties only, no methods.
        /// Useful to eliminate the need for creating data type classes to match your interfaces. 
        /// </summary>
        /// <typeparam name="T">An interface that declares only properties, not methods</typeparam>
        void RegisterInterfacesAsDataTypes(List<Type> interfaceTypes);
    }
}
